/***************************************************
File:           LPK_BaseClass.cs
Authors:        Christopher Onorati
Last Updated:   5/20/2019
Last Version:   2018.3.14

Description:
  This script contains the base class all LPK objects
  inheret from.

Copyright 2018-2019, DigiPen Institute of Technology
***************************************************/

using System.Collections.Generic;
using UnityEngine;
using LPK_CONSOLE;  /* Developer console to print log messages. */

namespace LPK
{

/**
* CLASS NAME  : LPK_Component
* DESCRIPTION : Base object for all LPK objects to inherited off of.
**/
public class LPK_Component : MonoBehaviour
{
    /************************************************************************************/

    //Print debug info.
    public bool m_bPrintDebug = false;

    //Label per-component.  Does not do anything, just allows notes in the inspector.
    public string m_sLabel;

    /************************************************************************************/

    //Flag to check if the console has been spawned.
    static bool m_bHasSpawnedConsole = false;

    /**
    * FUNCTION NAME: Start
    * DESCRIPTION  : Sets up pause event listening and calls OnStart.
    * INPUTS       : None
    * OUTPUTS      : None
    **/
    void Start()
    {
        //Create the developer console.
        if(!m_bHasSpawnedConsole)
        {
            string path = "Prefabs/LPK/Core/DeveloperConsole";
            GameObject devConsole = Resources.Load(path) as GameObject;
            Instantiate(devConsole);

            m_bHasSpawnedConsole = true;
        }

        OnStart();
    }

    /**
    * FUNCTION NAME: OnStart
    * DESCRIPTION  : Implemented by child classes.
    * INPUTS       : None
    * OUTPUTS      : None
    **/
    protected virtual void OnStart()
    {
        //Implemented by child classes so start will always be called.
    }

    /**
    * FUNCTION NAME: LPK_PrintDebug
    * DESCRIPTION  : Prints a formatted debug message.
    * INPUTS       : _caller  - Unity object (component) that invoked this function.
    *                _message - Additional message to print along with caller data.
    * OUTPUTS      : None
    **/
    protected void LPK_PrintDebug(Object _caller, string _message)
    {
        Debug.Log(_message + " | " + _caller + " | " + gameObject.name);
        LPK_DeveloperConsole.AddMessageToConsole("[LOG] " + _message + " | " + _caller + " | " + gameObject.name);
    }

    /**
    * FUNCTION NAME: LPK_PrintWarning
    * DESCRIPTION  : Prints a formatted debug warning.
    * INPUTS       : _caller  - Unity object (component) that invoked this function.
    *                _message - Additional message to print along with caller data.
    * OUTPUTS      : None
    **/
    protected void LPK_PrintWarning(Object _caller, string _message)
    {
        Debug.LogWarning(_message + " | " + _caller + " | " + gameObject.name);
        LPK_DeveloperConsole.AddMessageToConsole("[WARNING] " + _message + " | " + _caller + " | " + gameObject.name);
    }

    /**
    * FUNCTION NAME: LPK_PrintError
    * DESCRIPTION  : Prints a formatted debug error.
    * INPUTS       : _caller  - Unity object (component) that invoked this function.
    *                _message - Additional message to print along with caller data.
    * OUTPUTS      : None
    **/
    protected void LPK_PrintError(Object _caller, string _message)
    {
        Debug.LogError(_message + " | " + _caller + " | " + gameObject.name);
        LPK_DeveloperConsole.AddMessageToConsole("[ERROR] " + _message + " | " + _caller + " | " + gameObject.name);
    }

    /**
    * FUNCTION NAME: OnEvent
    * DESCRIPTION  : Empty function overriden to handle script action implementation.
    * INPUTS       : _activator - Activator specified for the event.  If null, all objects are considered the acivator.
    * OUTPUTS      : None
    **/
    public virtual void OnEvent(GameObject _activator)
    {
        //Implemented in each indivitual script.
    }

    /**
    * FUNCTION NAME: ShouldRespondToEvent
    * DESCRIPTION  : Checks if the event should be activated based on activator game object.
    * INPUTS       : _activator - Activator specified for the event.  If null, all objects are considered the acivator.
    * OUTPUTS      : true/false value of if the OnEvent function should be activated.
    **/
    protected bool ShouldRespondToEvent(GameObject _activator)
    {
        if(_activator != null && _activator != gameObject)
            return false;

        return true;
    }

    /**
    * FUNCTION NAME: GetGameObjectsInRadius
    * DESCRIPTION  : Fills a list with gameobjects found within a certain radius of the owner gameobject.
    * INPUTS       : _Gameobjects     - List to return objects in.
    *                _radius          - Max distance an object can be to be valid.
    *                _objectCount     - How many objects to find.  -1 is as many as possible.
    *                _tagName         - Specify to search for a specific tag.  This is much less expensive.
    * OUTPUTS      : None
    **/
    public void GetGameObjectsInRadius(List<GameObject> _gameObjects, float _radius, int _objectCount = -1, string _tagName = "")
    {
        GameObject[] taggedObjects = GameObject.FindGameObjectsWithTag(_tagName);

        for (int i = 0; i < taggedObjects.Length; i++)
        {
            if(Vector3.Distance(taggedObjects[i].transform.position, transform.position) <= _radius)
            {
                _gameObjects.Add(taggedObjects[i]);
                _objectCount--;

                if (_objectCount == 0)
                    break;
            }
        }
    }
}

/**
* CLASS NAME  : LPK_EventSendingInfo
* DESCRIPTION : Event sending info for LPK events.
**/
[System.Serializable]
public class LPK_EventSendingInfo
{
    /************************************************************************************/

    public enum LPK_EventSendingMode
    {
        OWNER,
        ALL,
    };

    [Tooltip("Event sending mode.  OWNER = only send to components on the same game object.  ALL = send to all game objects")]
    public LPK_EventSendingMode m_EventSendingMode = LPK_EventSendingMode.ALL;

    [Tooltip("Event to dispatch when conditions are met.")]
    public LPK_EventObject m_Event;
}

/**
* CLASS NAME  : LPK_CollisionEventSendingInfo
* DESCRIPTION : Event sending info for LPK events with added "other" mode.
**/
[System.Serializable]
public class LPK_CollisionEventSendingInfo
{
    /************************************************************************************/

    public enum LPK_EventSendingMode
    {
        OTHER,
        OWNER,
        ALL,
    };

    [Tooltip("Event sending mode.  OTHER = onyl send to components on the game object that caused the collision.  OWNER = only send to components on the same game object.  ALL = send to all game objects")]
    public LPK_EventSendingMode m_EventSendingMode;

    [Tooltip("Event to dispatch when conditions are met.")]
    public LPK_EventObject m_Event;
}

}   //LPK
